package bdz.projects.lavender.cms.core
{
	import bdz.common.events.UploadManagerEvent;
	import bdz.common.events.XMLLoaderEvent;
	import bdz.common.managers.UploadManager;
	import bdz.common.model.XMLLoader;
	import bdz.projects.lavender.cms.events.CMSEvent;
	import bdz.projects.lavender.cms.model.DataModel;
	
	import flash.display.BitmapData;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLVariables;
	import flash.utils.ByteArray;
	
	public class CMSGateway extends EventDispatcher
	{
		private static var instance:CMSGateway;
		private static var configuration:CMSConfig;
		private static var dmodel:DataModel;
		private var umanager:UploadManager;
		private var currentuploader:Function;
		private var _sessionKeys:Object;
		private var _appID:String;
		public function CMSGateway(se:SingletonEnforcer)
		{
			
		}
		public static function getGateway(config:CMSConfig):CMSGateway{
			if(!instance){
				instance = new CMSGateway(new SingletonEnforcer());
				instance.initialize(config);
			}
			return instance;
		}
		private function applyKey(obj:*):*{
			obj.Key1 = _sessionKeys.key1;
			obj.Key2 = _sessionKeys.key2;
			return obj;
		}
		private function initialize(config:CMSConfig):void{
			configuration = config;
			
		}
		private function dispatchDataProgress():void{
			dispatchEvent(new CMSEvent(CMSEvent.SAVE_PROGRESS));
		}
		private function dispatchUploadProgress(evt:UploadManagerEvent):void{
			dispatchEvent(evt);	
		}
		private function dispatchUploadError(evt:Event):void{
			dispatchEvent(evt);
		}
		private function dispatchUploadComplete(evt:UploadManagerEvent):void{
			currentuploader(evt);
			dispatchEvent(evt);
		}
		private function dispatchUploadStart(evt:UploadManagerEvent):void{
			dispatchEvent(evt);
		}
		private function checkError(dta:XML):Boolean{
			return dta.name().toString() != "error";
		}
		private function onLoginComplete(evt:XMLLoaderEvent):void{
			
			var dta:XML = new XML(evt.data);
			if(dta.children().length()){
				dispatchEvent(new CMSEvent(CMSEvent.LOGIN_SUCCESS, dta));
			}else{
				dispatchEvent(new CMSEvent(CMSEvent.ERROR, "Account not found."));
			}
		}
		private function onLoginFault(evt:XMLLoaderEvent):void{
			var dta:XML = new XML(evt.data);
			dispatchEvent(new CMSEvent(CMSEvent.LOGIN_FAILED, dta.toString()));
		}
		private function onLoginIOError(evt:XMLLoaderEvent):void{
			/*
			
			CHANGE LATER
			
			*/
			//dispatchEvent(new CMSEvent(CMSEvent.LOGIN_SUCCESS));
			dispatchEvent(new CMSEvent(CMSEvent.ERROR, "Could not connect to server"));
		}
		private function onRootRetrieved(evt:XMLLoaderEvent):void{
			var dta:XML = new XML(evt.data);
			if(checkError(dta)){
				dmodel = DataModel.getModel(dta);
				dispatchEvent(new CMSEvent(CMSEvent.ROOT_RETRIEVED, dmodel));
			}else{
				dispatchEvent(new CMSEvent(CMSEvent.ERROR, dta.toString()));
			}
			
		}
		private function onRootFault(evt:XMLLoaderEvent):void{
			
		}
		private function onContentRetrieved(evt:XMLLoaderEvent):void{
			
		}
		private function onContentFault(evt:XMLLoaderEvent):void{
			
		}
		private function onDataDeleteFault(evt:*):void{
			dispatchEvent(new CMSEvent(CMSEvent.ERROR));
		}
		private function onDataDeleted(evt:XMLLoaderEvent):void{
			dispatchEvent(new CMSEvent(CMSEvent.OBJECT_DELETED, dmodel));
		}
		private function onContentSaved(evt:XMLLoaderEvent):void{
			dispatchEvent(new CMSEvent(CMSEvent.OBJECT_MODIFIED, dmodel));
		}
		private function onContentSaveFault(evt:XMLLoaderEvent):void{
			dispatchEvent(new CMSEvent(CMSEvent.ERROR));
		}
		private function onBytesUploaded(evt:XMLLoaderEvent):void{
			dispatchEvent(new CMSEvent(CMSEvent.BYTES_UPLOADED, evt.data));	
		}
		private function onBytesFault(evt:XMLLoaderEvent):void{
			
		}
		private function onCMSError(evt:*):void{
			dispatchEvent(new CMSEvent(CMSEvent.ERROR, "Could not connect to server"));
		}
		private function onTemplateRetrieveError(evt:XMLLoaderEvent):void{
			dispatchEvent(new CMSEvent(CMSEvent.ERROR, "Error retrieving template data"));
		}
		private function createUploadManager(onselect:Function, uvars:Object = null):void{
			umanager = new UploadManager();
			umanager.addEventListener(UploadManagerEvent.UPLOAD_COMPLETE, dispatchUploadComplete);
			umanager.addEventListener(Event.SELECT, onselect);
			umanager.addEventListener(IOErrorEvent.IO_ERROR, dispatchUploadError);
			umanager.addEventListener(SecurityErrorEvent.SECURITY_ERROR, dispatchUploadError);
			umanager.addEventListener(UploadManagerEvent.UPLOAD_START, dispatchUploadStart);
			if(uvars){
				for(var prop:String in uvars){
					umanager.addVariables(prop, uvars[prop]);
				}
			}
			umanager.url = configuration.baseURL+CMSMethod.UPLOAD;
		}
		/**
		 * PUBLIC METHODS
		 */
		
		public function login(uname:String, pword:String):void{
			var uvars:URLVariables = new URLVariables();
			uvars.acmsAppID = configuration.applicationID;
			
			uvars.prmEmail = uname;
			uvars.prmPassword = pword;
			
			var xm:XMLLoader = new XMLLoader();
			xm.location = configuration.baseURL+CMSMethod.LOGIN;
			
			xm.addEventListener(XMLLoaderEvent.RESULT, onLoginComplete);
			xm.addEventListener(XMLLoaderEvent.FAULT, onLoginFault);
			xm.addEventListener(XMLLoaderEvent.IOFAULT, onLoginIOError);
			xm.send(uvars);
		}
		public function getPlugins(res:Function):void{
			var uvars:URLVariables = new URLVariables();
			uvars.ApplicationID = configuration.applicationID;
			uvars = applyKey(uvars);
			
			var xm:XMLLoader = new XMLLoader();
			xm.location = configuration.baseURL+CMSMethod.GET_PLUGINS;
			xm.addEventListener(XMLLoaderEvent.RESULT, res);
			xm.addEventListener(XMLLoaderEvent.FAULT, onCMSError);
			xm.addEventListener(XMLLoaderEvent.IOFAULT, onCMSError);
			xm.send(uvars);
		}
		public function getSubContent(id:String, recurse:String = ""):void{
			var uvars:URLVariables = new URLVariables();
			uvars.acmsAppID = configuration.applicationID;
			uvars = applyKey(uvars);
			uvars.acmsObjectID = id;
			uvars.acmsRecurse = recurse;
			
			var xm:XMLLoader = new XMLLoader();	
			xm.location = configuration.baseURL+CMSMethod.GET_OBJECTS;
			xm.addEventListener(XMLLoaderEvent.IOFAULT, onCMSError);
			xm.addEventListener(XMLLoaderEvent.RESULT, onContentRetrieved);
			xm.addEventListener(XMLLoaderEvent.FAULT, onContentFault);
			xm.send(uvars);
		}
		public function getRoot():void{
			
			var uvars:URLVariables = new URLVariables();
			uvars.acmsAppID = configuration.applicationID;
			uvars = applyKey(uvars);
			uvars.acmsObjectID = "";
			uvars.acmsRecurse = ""
			
			var xm:XMLLoader = new XMLLoader();	
			xm.location = configuration.baseURL+CMSMethod.GET_OBJECTS;
			
			xm.addEventListener(XMLLoaderEvent.RESULT, onRootRetrieved);
			xm.addEventListener(XMLLoaderEvent.FAULT, onRootFault);
			xm.send(uvars);
		}
		public function postImageBytes(bytes:ByteArray, filename:String):void{
			var xm:XMLLoader = new XMLLoader();
			
			xm.location = configuration.baseURL+CMSMethod.UPLOAD;
			
			xm.addEventListener(XMLLoaderEvent.IOFAULT, onCMSError);
			xm.addEventListener(XMLLoaderEvent.RESULT, onBytesUploaded);
			xm.addEventListener(XMLLoaderEvent.FAULT, onBytesFault);
			xm.sendPostHelp(new Object(), filename, bytes);
		}
		/**
		 * 
		 */
		
		public function saveBatch(xdata:XML, handler:Function = null):void{
			
			var uvars:URLVariables = new URLVariables();
			/*
			 * WRAP INFORMATION UNDER THE APPLICATION NODE
			 */
			var xsave:XML = new XML("<application/>");
			xsave[xdata.name().toString()] = xdata;
			uvars.acmsXMLFormatedData = xdata;
			uvars = applyKey(uvars);
			
			var xm:XMLLoader = new XMLLoader();	
			xm.location = configuration.baseURL+CMSMethod.SAVE_XML;
			xm.addEventListener(XMLLoaderEvent.IOFAULT, onCMSError);
			xm.addEventListener(XMLLoaderEvent.RESULT, handler || onContentSaved);
			xm.addEventListener(XMLLoaderEvent.FAULT, onContentSaveFault);
			xm.send(uvars);
			
		}
		public function insertData(pid:String, dta:XML, handler:Function):void{
			var uvars:URLVariables = new URLVariables();
			uvars.ApplicationID = configuration.applicationID;
			uvars = applyKey(uvars);
			uvars.ParentObjectID = pid;
			var xsave:XML = new XML("<application/>");
			xsave[dta.name().toString()] = dta;
			uvars.ObjectXML = dta;
			
			var xm:XMLLoader = new XMLLoader();
			xm.location = configuration.baseURL+CMSMethod.INSERT_DATA;
			
			xm.addEventListener(XMLLoaderEvent.RESULT, handler);
			xm.addEventListener(XMLLoaderEvent.FAULT, onCMSError);
			xm.addEventListener(XMLLoaderEvent.IOFAULT, onCMSError);
			xm.send(uvars);
			
		}
		public function rawProcess(location:String, uvars:URLVariables, successHandler:Function, errorHandler:Function = null, progressHandler:Function = null):void{
			var xm:XMLLoader = new XMLLoader();
			xm.location = location;
			xm.addEventListener(XMLLoaderEvent.RESULT, successHandler);
			if(errorHandler != null){
				xm.addEventListener(XMLLoaderEvent.FAULT, errorHandler);
				xm.addEventListener(XMLLoaderEvent.IOFAULT, errorHandler);
			}
			xm.send(uvars);
		}
		public function retrieveTemplate(handler:Function, oid:String):void{
			var uvars:URLVariables = new URLVariables();
			uvars = applyKey(uvars);
			uvars.OjectTypeID = oid;
			uvars.WithContainerFlag_Y = "";
			
			var xm:XMLLoader = new XMLLoader();	
			xm.location = configuration.baseURL+CMSMethod.GET_TEMPLATE;
			xm.addEventListener(XMLLoaderEvent.RESULT, handler);
			xm.addEventListener(XMLLoaderEvent.FAULT, onTemplateRetrieveError);
			xm.addEventListener(XMLLoaderEvent.IOFAULT, onTemplateRetrieveError);
			
			xm.send(uvars);
		}
		public function browseForImage(onselect:Function, oncomplete:Function, uvars:Object = null):void{
			currentuploader = oncomplete;
			createUploadManager(onselect, uvars);
			umanager.browseForImage();
		}
		public function browseForFile(onselect:Function, oncomplete:Function, uvars:Object = null):void{
			currentuploader = oncomplete;
			createUploadManager(onselect, uvars);
			umanager.browseAllTypes();
		}
		public function deleteObject(oid:String):void{
			var uvars:URLVariables = new URLVariables();
			uvars = applyKey(uvars);
			uvars.prmObj = oid;
			
			
			var xm:XMLLoader = new XMLLoader();	
			xm.location = configuration.baseURL+CMSMethod.DELETE_DATA;
			xm.addEventListener(XMLLoaderEvent.RESULT, onDataDeleted);
			xm.addEventListener(XMLLoaderEvent.FAULT, onDataDeleteFault);
			xm.addEventListener(XMLLoaderEvent.IOFAULT, onDataDeleteFault);
			
			xm.send(uvars);
		}
		public function upload():void{
			umanager.uploadFile();
		}
		
		public function createThumbnail(bmp:BitmapData, w:Number, h:Number):void{
			
		}
		/**
		 * PUBLIC PROPERTIES
		 */
		public function set sessionKeys(obj:Object):void{
			_sessionKeys = obj;
		}
		public function set appID(str:String):void{
			_appID = str;
		}
		public static function get config():CMSConfig{
			return configuration;
		}
		public function get model():DataModel{
			return dmodel;
		}
		public function set model(dm:DataModel):void{
			dmodel = dm;
		}

	}
}
/**
 * @private
 * 
 */
internal class SingletonEnforcer{}